package edu.bbu.cshu.wmpc.dao.jdbc;

import edu.bbu.cshu.wmpc.core.FileTypes;
import edu.bbu.cshu.wmpc.core.SourceCodeWmpc;
import edu.bbu.cshu.wmpc.dao.CodeDAO;
import edu.bbu.cshu.wmpc.ioLocal.FileContentProvider;
import edu.bbu.cshu.wmpc.loggin.EventLogger;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Random;
import org.apache.log4j.Level;
/**
 * <ul>
 * <li><b><i>CodeJdbcDAO</i></b></li>
 * <li style="list-style: none;"></li>
 * <li style="list-style: none;">
 * Class that implements {@link CodeDAO} using Java Database Connectivity.
 * 
 * @author WMPC team
 * </li>
 * </ul>
 */ 
public class CodeJdbcDAO implements CodeDAO {
	/**
	 * <ul>
	 * <li><b><i>con</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * {@link Connection} being opened and closed at the beginning and end of every function that communicates with the database.  
	 * 
	 * </li>
	 * </ul>
	 */
	private Connection con = null;

	@Override
	public void insertFile(String URL) throws Exception {
		Random rand  = new Random();
    	String name = URL.substring(URL.lastIndexOf('/')+1, URL.length());	
    	FileInputStream fin = new FileInputStream(URL);
		File file = new File(URL);
    	PreparedStatement pstmt = null;
    	
		try {
        	con = ConnectionManager.INSTANCE.createConnection();
        	
        	pstmt = con.prepareStatement("INSERT INTO filecontents (id,name,content) VALUES (?,?,?)");
			pstmt.setInt(1, 100000000+rand.nextInt(900000000));
			pstmt.setString(2, name);
			pstmt.setBinaryStream(3, fin, (int) file.length());
			pstmt.execute();
			
        } catch(Exception e) {
            String msg = "Error in edu.bbu.cshu.wmpc.dao.jdbc.CodeJdbcDAO.insertFile:\n"+e.getMessage();
            EventLogger.INSTANCE.writeToLog(Level.ERROR, msg);
        } finally {
            ConnectionManager.INSTANCE.closeConnection(con);
        }
	}

	@SuppressWarnings("finally")
	@Override
	public ArrayList<String> getFileById(int id) throws Exception {
		ArrayList<String> list = new ArrayList<>();
		String name = "";
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		InputStream fin = null;
		
		try {
        	con = ConnectionManager.INSTANCE.createConnection();
			
        	pstmt = con.prepareStatement("SELECT name,content FROM filecontents WHERE id = ?");
			pstmt.setInt(1, id);
			rs = pstmt.executeQuery();
			
			if (rs.next()) {
				name = rs.getString(1);
				fin =  (ByteArrayInputStream) rs.getBinaryStream(2);
			}
			
			list.add("##### "+name+" #####");
			list.addAll(FileContentProvider.INSTANCE.contentFromStream(fin));
			
        } catch(Exception e) {
            String msg = "Error in edu.bbu.cshu.wmpc.dao.jdbc.CodeJdbcDAO.getFileById:\n"+e.getMessage();
            EventLogger.INSTANCE.writeToLog(Level.ERROR, msg);
        } finally {
            ConnectionManager.INSTANCE.closeConnection(con);
            return list;
        }
	}

	@SuppressWarnings("finally")
	@Override
	public ArrayList<String> getFileByName(String name) throws Exception {
		ArrayList<String> list = new ArrayList<>();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		InputStream fin = null;
		
		try {
        	con = ConnectionManager.INSTANCE.createConnection();
			
        	pstmt = con.prepareStatement("SELECT content FROM filecontents WHERE name = ?");
			pstmt.setString(1, name);
			rs = pstmt.executeQuery();
			
			if (rs.next()) {
				fin =  (ByteArrayInputStream) rs.getBinaryStream(1);
			}
			
			list.add("##### "+name+" #####");
			list.addAll(FileContentProvider.INSTANCE.contentFromStream(fin));
			
        } catch(Exception e) {
            String msg = "Error in edu.bbu.cshu.wmpc.dao.jdbc.CodeJdbcDAO.getFileByName:\n"+e.getMessage();
            EventLogger.INSTANCE.writeToLog(Level.ERROR, msg);
        } finally {
            ConnectionManager.INSTANCE.closeConnection(con);
            return list;
        }
	}

	@SuppressWarnings("finally")
	@Override
	public SourceCodeWmpc getAllFileContents(String group, FileTypes type) throws Exception {
		SourceCodeWmpc sc = new SourceCodeWmpc(type);
		ArrayList<String> list = new ArrayList<>();
		String name = "";
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		InputStream fin = null;
		
		try {
        	con = ConnectionManager.INSTANCE.createConnection();
			
        	pstmt = con.prepareStatement("SELECT name,content FROM filecontents WHERE name LIKE '"+group+"%'");
			rs = pstmt.executeQuery();
			
			while (rs.next()) {
				name = rs.getString(1);
				fin =  (ByteArrayInputStream) rs.getBinaryStream(2);
				
				list.add("##### "+name+" #####");
				list.addAll(FileContentProvider.INSTANCE.contentFromStream(fin));
			}
			sc.setOriginal(list);
			
        } catch(Exception e) {
            String msg = "Error in edu.bbu.cshu.wmpc.dao.jdbc.CodeJdbcDAO.getAllFileContents:\n"+e.getMessage();
            EventLogger.INSTANCE.writeToLog(Level.ERROR, msg);
        } finally {
            ConnectionManager.INSTANCE.closeConnection(con);
            return sc;
        }
	}
    
	@SuppressWarnings("finally")
	@Override
	public ArrayList<String> getAllFileInfos(FileTypes type) throws Exception {
		ArrayList<String> list = new ArrayList<String>();
		String name = "";
		String query = "";
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
        	con = ConnectionManager.INSTANCE.createConnection();
			
        	switch (type) {
        		case CPP:
        			query = "SELECT name FROM filecontents WHERE name LIKE '%c' OR name LIKE '%cpp' OR name like '%h'";
        			break;
        		case JAVA:
        			query = "SELECT name FROM filecontents WHERE name LIKE '%java'";
        			break;
        		case PASCAL:
        			query = "SELECT name FROM filecontents WHERE name LIKE '%pas'";
        			break;
        	}
        	pstmt = con.prepareStatement(query);
			rs = pstmt.executeQuery();
			
			while (rs.next()) {
				name = rs.getString(1);
				name = name.substring(0, name.lastIndexOf('.'));
				if (!name.substring(name.lastIndexOf('_')+1, name.length()).matches("[a-z]{4}[0-9]{4}"))
					name = name.substring(0, name.lastIndexOf('_'));
				if (!list.contains(name)) {
					list.add(name);
				}
			}
        	
        } catch(Exception e) {
            String msg = "Error in edu.bbu.cshu.wmpc.dao.jdbc.CodeJdbcDAO.getAllFileInfos:\n"+e.getMessage();
            EventLogger.INSTANCE.writeToLog(Level.ERROR, msg);
        } finally {
            ConnectionManager.INSTANCE.closeConnection(con);
            return list;
        }
	}
}
